
package com.kinth.work.zggys3;
import java.io.File;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.xml.DOMConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.scheduler.PriorityScheduler;

/**
 * 
 * <p>
 * Title: 获得总的列表ip.
 * </p>
 * <p>
 * 1. 一个新的公司入口页：https://www.china.cn/xinzenggongsi/2007-01-05.html
 * Description: 首先是https://www.china.cn/xinzenggongsi/2007-01-05.html,这是总的起始页。
 * 然后分层提取，并给url设置优先级。这样，公司页面的将是最高优先级的。
 * 不过这还是需要一次性存储很多的url。不过经过测试应该可以。
 * 关于ip问题，解决方法就是时间延迟。自己无法控制request的请求时间，因为封装在框架里面。而且都是死有函数，无法覆写。所以
 * 就在添加request的时候添加延迟。每五秒一个。但是通过观察数据库上面的数据，还是一秒一个较多。应该是添加了之后一直
 * 累积在一起，然后一段时间一起爬取
 * 
 * ******************************************************************
 * 4月26日更新：
 * 1. 因为昨天服务器上面的代码中断，所以又进行了更改。
 * 2. 中国供应商网为什么中断不知道。
 * 3. 另外，添加了定位，如果下次中断，直接重启即可。
 * 4. 开始从现在往前面搜。
 * 5. 添加了先抓取全部页数的功能。
 * 6. 目前，log会放在和项目的相同父目录下。定位文件locate.txt也是如此。上传更新时请一起。
 * </p>
 * 
 * *******************************************************************
 * 5月9号更新：
 * 1. 因为一个新的问题，就是所有的列表页第一页是被忽略的。后来发现应该是page内置的去重导致的。因为都是01,
 * 导致作为公司列表页和公司列表入口的链接一样，这样后面的会被屏蔽。所以吧后面改成1.
 * 2. 不要使用spider.setExitWhenComplete(false);会卡主。目前的在循环中run就可以。
 * 
 * @author kaikai
 * @2017年4月1日
 */
public class MainForzggys3 implements PageProcessor
{
	private Site site = Site.me().setUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 "
			+ "(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36").setRetryTimes(3).setSleepTime(100);

	public static final String BIG_URL = "https://www.china.cn/xinzenggongsi/\\d{4}-\\d{2}-\\d{2}_\\d{1,3}.html";

	public  static final String COMPANY_URL = "https://[a-zA-Z0-9]+.cn.china.cn";
	
	//添加每个链接的延迟，为了不被ip屏蔽
    public static final int SLEEP_TIME = 5000;
    
    protected Logger logger = LoggerFactory.getLogger(getClass());
    
	@Override
	public void process(Page page)
	{
		//System.out.println("process: "+page.getUrl().toString());
		
		if(page.getUrl().regex(BIG_URL).match())
		{
			//System.out.println("1");
			try{
				if(page.getRequest().getExtra("list") == null)
				{
					processBigUrl0(page);
				}else
				{
					processBigUrl(page);
				}
				
			}catch(Exception e)
			{
				logger.error("bigurl:  "  + " error", e);
			}
			
		}else if(page.getUrl().regex(COMPANY_URL).match())
		{
			//System.out.println("4");
			try{
				getInfo(page);
			}catch(Exception e)
			{
				logger.error("companyurl:  "  + " error", e);
			}
			
		}


	}

	//处理公司页面
	public void getInfo(Page page) throws Exception
	{

		
		String name = page.getHtml()
				.xpath("//body/div[@class='content-wrapper']" + "/div[@class='bd']/div[@class='content fl-clr']"
						+ "/div[@class='con-lef']/div[@id='det_info']/div[@class='lef-bd']"
						+ "/ul/li[@class='comp']/h3/a/text()")
				.toString();
		if (name == null)
		{

			name = page
					.getHtml().xpath("//body" + "//div[@class='content fl-clr']"
							+ "//div[@id='det_info']/div[@class='lef-bd']" + "/ul//div[@class='comp']/a/text()")
					.toString();

		}
		String people = null;
		String address = null;
		String phone1 = null;
		String phone2 = null;
		String phone3 = null;
		String qq = null;
		String introduction = null;
		String product = null;

		if (name != null)
		{
			// 产品
			product = page.getHtml().xpath("//head/title/text()").toString();

			// 产品介绍
			introduction = page.getHtml().xpath("//body" + "//div[@class='content fl-clr']"
					+ "//div[@id='det_info']/div[@class='lef-bd']" + "/ul/li[5]").toString();
			if (introduction == null)
			{
				introduction = page.getHtml()
						.xpath("//body" + "//div[@class='content fl-clr']" + "//div[@class='company-info']/p/text()")
						.toString();
			}
			//替换取出提取的字符串里面的html代码
			String regex;
			regex = "<[\\s\\S]*?>";
			introduction = introduction.replaceAll(regex, "").trim();
			introduction = introduction.replaceAll("\n", "");

			// 对联系方式里面的利用循环处理
			int amount = 7;
			for (int i = 1; i <= amount; i++)
			{
				String tempKey = page
						.getHtml().xpath("//body" + "//div[@class='content fl-clr']"
								+ "//div[@id='contact']/div[@class='lef-bd']" + "/ul/li[" + i + "]/dl/dt/text()")
						.toString();
				String tempValue = page
						.getHtml().xpath("//body" + "//div[@class='content fl-clr']"
								+ "//div[@id='contact']/div[@class='lef-bd']" + "/ul/li[" + i + "]/dl/dd/text()")
						.toString();
				if (tempKey == null)
				{
					break;
				}
				if (tempKey.substring(0, 1).equals("联"))
				{
					people = tempValue;

				} else if (tempKey.substring(0, 1).equals("职"))
				{
					String people2 = tempValue;

					// 联系人加职位
					people = people + " " + people2;

				} else if (tempKey.substring(0, 1).equals("电"))
				{
					phone1 = tempKey + tempValue;

				} else if (tempKey.substring(0, 1).equals("手"))
				{
					phone2 = tempKey + tempValue;

				} else if (tempKey.substring(0, 1).equals("传"))
				{
					phone3 = tempKey + tempValue;

				} else if (tempKey.substring(0, 1).equals("地"))
				{
					address = tempKey + tempValue;

				}
				if (tempKey.substring(0, 1).equals("客"))
				{
					qq = page.getHtml()
							.xpath("//body" + "//div[@class='content fl-clr']"
									+ "//div[@id='contact']/div[@class='lef-bd']" + "/ul/li[" + i + "]/dl/dd/a")
							.toString();
					if (qq != null)
					{
						String qqTemp[] = qq.split("=");
						
						if (qqTemp.length >= 2)
						{
							qq = qqTemp[1];
							qqTemp = qq.split("\\(");
							if (qqTemp.length >= 2)
							{
								qq = qqTemp[1];
								qqTemp = qq.split(",");
								if (qqTemp.length >= 2)
								{
									qq = qqTemp[0];
								} else
								{
									qq = null;
								}
							} else
							{
								qq = null;
							}
						} else
						{
							qq = null;
						}
					}
				}

			}

		}

		logger.info("getinfo:爬取具体信息  " +page.getUrl());
		//System.out.println("测试5： ");
		String urlNow = page.getUrl().toString();
		//String industry = page.getRequest().getExtra("industry").toString();
		page.putField("name", name);
		page.putField("product", product);
		page.putField("address", address);
		page.putField("people", people);
		page.putField("qq", qq);
		page.putField("introduction", introduction);
		page.putField("phone1", phone1);
		page.putField("phone2", phone2);
		page.putField("phone3", phone3);
		//page.putField("industry", industry);
		page.putField("url", urlNow);

	}
	//得到全部页数，然后转换得到全部列表页
	public void processBigUrl0(Page page) throws Exception
	{
		String pageNumStr = page.getHtml()
				.xpath("//body/div[@class='content']" 
				        + "/div[@class='product_box']/div[@class='Pagination']//span[@class='pageNum']/text()")
						.toString();
		
		//System.out.println("测试下一页的url： "+pageNumStr);
		
		int pageNum = 1;
		if(pageNumStr != null && !pageNumStr.isEmpty())
		{
			String sTemp2[] = pageNumStr.split(" ");
			if(sTemp2.length == 6)
			{
				try{
					pageNum = Integer.parseInt(sTemp2[1]);
					//System.out.println("pageNum: "+pageNum);
				}catch(Exception e)
				{
					logger.error("pageNum is not a num: "+pageNumStr);
				}
				
			}
			
		}
		String urlNow = page.getUrl().toString();
		String foreString = urlNow.substring(0,urlNow.length()-7);
		
		for(int i = 1; i <= pageNum; i++)
		{
			String url = foreString + i+".html";
			logger.info("得到每个列表页："+url);
			//System.out.println("url: "+url);
			Request request = new Request(url).putExtra("list", "list").setPriority(1);
		       
			page.addTargetRequest(request); 
		}
	}
	//处理列表页
	public void processBigUrl(Page page) throws Exception
	{
		ArrayList<String> companyList = new ArrayList<String>();
		
		companyList = (ArrayList<String>) page.getHtml()
				.xpath("//body/div[@class='content']" 
		        + "/div[@class='product_box']/ul[@class='product1_ul  fl-clr']")
				.links().all();
		
		if(companyList == null)
		{
			return;
		}

		for (String url : companyList)
		{
			
			logger.info("process3,得到公司链接: "+url);
			
			Request request = new Request(url).setPriority(2);
	       
			page.addTargetRequest(request); 
		}
		
		
	}
	
	@Override
	public Site getSite()
	{
		return site;
	}
    //返回特定年份的每月天数
    private static int dayPerMonth(int y, int m)
    {
    	int result = 0;
    	if((m==1) || (m==3) || (m==5) || (m==7) || (m==8) || (m==10) || (m==12))
    	{
    		result = 31;
    	}else if((m==4) || (m==6) || (m==9) || (m==11) )
    	{
    		result = 30;
    	}else if(m == 2)
    	{
    		if(isLeapYear(y))
    		{
    			result = 29;
    		}else
    		{
    			result = 28;
    		}
    	}
    	
    	return result;
    }
	//判断是不是闰年
	private static boolean isLeapYear(int y)
	{
		boolean flag = false;
		if((y % 4 == 0 && y % 100 != 0) || (y % 400) == 0)
			flag = true;
			
		return flag;
	}
	// 一个代替main函数的函数
	public static void runSpider() throws Exception
	{
		//不能通过
		//把url也存起来
		System.out.println("爬取类别链接开始");
		MainForzggys3 mainForzggys = new MainForzggys3();
		Spider spider = Spider.create(mainForzggys);
		//spider.setExitWhenComplete(false);
		
		//吧spider放到循环外面，这样就不用每次都new 了。
		spider
		.setScheduler(new PriorityScheduler())
		.addPipeline(new DataPipeline());
		//.run();

		String url = null;
		//一开始启动，从文件读取位置：
		 //File file = new File(System.getProperty("user.dir"));
	     // get parent dir
	     String path = System.getProperty("user.dir")+File.separator+"locate.txt"; 
	
	     String s = FileUtil.getBigUrl(path);
	     int startYear = 2017;
	     int startMonth = 1;
	     int startDay = 1;
	     int t = 1;//标记是不是第一次
	     
	     if(!(s == null || s.isEmpty() || s == ""))
	     {
	    	 String sTemp[] = s.split(" ");
	    	 if(sTemp.length == 3)
	    	 {
	    		 startYear = Integer.parseInt(sTemp[0]);
	    		 startMonth = Integer.parseInt(sTemp[1]);
	    		 startDay = Integer.parseInt(sTemp[2]);
	    	 }
	     }
		for(int y = startYear; y >= 2007; y--)
		{
			if(t > 1)
			{
				startMonth = 12;
				
			}
		for(int m = startMonth; m >= 1; m--)
		{
			
			int month = m;
			String monthString = month+"";
			if(month < 10)
			{
				monthString = "0"+monthString;
			}
			int dayAmount = dayPerMonth(y, m);
			if(t > 1)
			{
				startDay = dayAmount;
				
			}
		for(int j = startDay; j >= 1; j--)
		{
		
			int day = j;
			String dayString = day+"";
			
			//用来记录读取位置
		    FileUtil.writeBigUrl(path, y, month, day);
			
			if(day < 10)
			{
				dayString = "0"+dayString;
			}
		//for(int i = 1; i <= 2; i++)
		{
			url = "https://www.china.cn/xinzenggongsi/"+y+"-"+monthString+"-"+dayString+"_0"+1+".html";
			//System.out.println("测试status: "+spider.getStatus());
			
			spider.addUrl(url).run();;
			while(spider.getStatus()!=Spider.Status.Stopped)
			{
				
			try
			{
				Thread.sleep(10000);
			} catch (InterruptedException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			}
		}
		t++;
		
		}
		}
		
		}
	}

	public static void main(String[] args)
	{
		DOMConfigurator.configure(System.getProperty("user.dir")+File.separator+"log4j.xml");
		//System.out.println("测试路径: "+System.getProperty("user.dir"));
		try
		{
			runSpider();
		} catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		MainForzggys3 mainForzggys = new MainForzggys3();
//		Spider spider = Spider.create(mainForzggys);
//		String url = null;
//		url = "https://www.china.cn/xinzenggongsi/2016-02-28_01.html";
//		spider
//		.setScheduler(new PriorityScheduler())
//		//.addPipeline(new DataPipeline())
//		.addUrl(url).run();
	}

	
}